{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "92cb9274",
   "metadata": {},
   "source": [
    "## 3.操作数组\n",
    "\n",
    "### 3.1索引"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "66e3db0d",
   "metadata": {},
   "source": [
    "和列表不同，numpy数组可以不用两个中括号来索引二维数组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "af1558e6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "M = np.array([[1, 2], [3, 4], [5, 6]])\n",
    "M[2,1]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aca41117",
   "metadata": {},
   "source": [
    "打印一行或一列，有两种方法(用冒号的方法对打印列是比较方便的）\n",
    "\n",
    "同样我们也可以利用这种方法对数组进行赋值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "9c85fe31",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[3 4]\n",
      "[2 4 6]\n"
     ]
    }
   ],
   "source": [
    "print(M[1])\n",
    "print(M[:,1])#因为如果用单纯的索引，同一列的数字不在一个数组里，会比较麻烦"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fa2c8ec9",
   "metadata": {},
   "source": [
    "### 3.2切片"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "65e3fd97",
   "metadata": {},
   "source": [
    "切片的形式也是M[lower:upper:step]和列表切片没有本质区别"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "5776607e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1 2 3 4 5]\n",
      "[ 1 -2 -3  4  5]\n"
     ]
    }
   ],
   "source": [
    "#改变数组的值，切片的值也会随之改变\n",
    "A = np.array([1,2,3,4,5])\n",
    "print(A[:])#都为默认时，可以打两个冒号，也可以只打一个\n",
    "A[1:3]=[-2,-3]\n",
    "print(A[:])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c1a25856",
   "metadata": {},
   "source": [
    "当然对多维数组也可以使用切片，注意多个括号的嵌套"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "f3b1b749",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 0  1  2  3  4]\n",
      " [10 11 12 13 14]\n",
      " [20 21 22 23 24]\n",
      " [30 31 32 33 34]\n",
      " [40 41 42 43 44]]\n",
      "[[10 11]\n",
      " [20 21]]\n",
      "[[ 0  2  4]\n",
      " [20 22 24]\n",
      " [40 42 44]]\n"
     ]
    }
   ],
   "source": [
    "M=np.array([[n+m*10 for n in range(5)]for m in range(5)])\n",
    "print(M)\n",
    "print(M[1:3,0:2])\n",
    "print(M[::2,::2])#步长不为1"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "afb072db",
   "metadata": {},
   "source": [
    "### 3.3花式索引（Fancy Indexing）：适用不规则索引情况\n",
    "\n",
    "**索引可以不相连，可以把一个表示位置的列表放进去**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "69351931",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[10 11 12 13 14]\n",
      " [30 31 32 33 34]\n",
      " [40 41 42 43 44]]\n",
      "[11 32 44]\n"
     ]
    }
   ],
   "source": [
    "M=np.array([[n+m*10 for n in range(5)]for m in range(5)])\n",
    "row=[1,3,-1]\n",
    "print(M[row])\n",
    "col=[1,2,-1]\n",
    "print(M[row,col])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d8513fdf",
   "metadata": {},
   "source": [
    "***这种方法也可利用与有条件地选取一些元素***"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "4d069ea0",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[False, False, False, False, False],\n",
       "       [False, False,  True, False,  True],\n",
       "       [ True, False,  True, False,  True],\n",
       "       [ True, False,  True, False,  True],\n",
       "       [ True, False,  True, False,  True]])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "condition=(M>10)*(M%2==0)#选取大于10的偶数\n",
    "condition"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "2213e516",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([12, 14, 20, 22, 24, 30, 32, 34, 40, 42, 44])"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "M[condition]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "698888dd",
   "metadata": {},
   "source": [
    "ps:在机器学习中常通过使用花式索引来打乱数据集的样本顺序，避免机器学习模型学习到样本的位置噪声，对于监督学习的数据集如果打乱了样本还需要打乱相对应的标签值，样本与标签都是一一对应的关系，使用花式索引能够轻松的解决。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a4548a47",
   "metadata": {},
   "source": [
    "**这种索引的位置还可以通过where函数进行返回**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "8afd18b9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4]),\n",
       " array([2, 4, 0, 2, 4, 0, 2, 4, 0, 2, 4]))"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "position=np.where(condition)\n",
    "position#结果里面的两个array分别表示第一个和第二个维度里面 有几个、在哪里\n",
    "#array1表示的是第一维里面每个数组有几个，array2表示每个数组里面True的在哪里"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ca7395f1",
   "metadata": {},
   "source": [
    "**使用diag函数可以提取 主、亚对角线元素**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "e8ac66f7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 0  1  2  3  4]\n",
      " [10 11 12 13 14]\n",
      " [20 21 22 23 24]\n",
      " [30 31 32 33 34]\n",
      " [40 41 42 43 44]]\n",
      "[ 0 11 22 33 44]\n",
      "[10 21 32 43]\n"
     ]
    }
   ],
   "source": [
    "print(M)\n",
    "print(np.diag(M))\n",
    "print(np.diag(M,-1))#-表示左下角偏移，+表示右上角偏移"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "95701090",
   "metadata": {},
   "source": [
    "### 3.4 遍历数组的元素\n",
    "\n",
    "一般我们会尽量避免遍历的情况发生，因为会比较慢，但是万不得已时用for循环最好"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "e4ae3614",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n",
      "4\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "v=np.array([1,2,3,4])\n",
    "for element in v:\n",
    "    print(element)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b8ca28e5",
   "metadata": {},
   "source": [
    "enumerate函数在索引时会返回位置索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "ba1af472",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "row_idx 0 row [1 2]\n",
      "col_idx 0 element 1\n",
      "col_idx 1 element 2\n",
      "row_idx 1 row [3 4]\n",
      "col_idx 0 element 3\n",
      "col_idx 1 element 4\n"
     ]
    }
   ],
   "source": [
    "M = np.array([[1,2], [3,4]])\n",
    "for row_idx, row in enumerate(M):\n",
    "    print(\"row_idx\", row_idx, \"row\", row)\n",
    "    \n",
    "    for col_idx, element in enumerate(row):\n",
    "        print(\"col_idx\", col_idx, \"element\", element)\n",
    "       \n",
    "        # 更新矩阵：对每个元素求平方\n",
    "        M[row_idx, col_idx] = element ** 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "3276e07c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1,  4],\n",
       "       [ 9, 16]])"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "M"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
